<html>
<head><meta charset="utf-8"><title>nagisa doesn&#x27;t understand pin again · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html">nagisa doesn&#x27;t understand pin again</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="227638856"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227638856" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227638856">(Feb 24 2021 at 17:31)</a>:</h4>
<p>So, this is 2nd time I'm utterly confused by some things surrounding <code>Pin</code>. First, there's <a href="https://doc.rust-lang.org/stable/std/pin/index.html#drop-implementation">this section</a>, which specifically says:</p>
<blockquote>
<p>Moreover, if your type is #[repr(packed)], the compiler will automatically move fields around to be able to drop them. It might even do that for fields that happen to be sufficiently aligned. As a consequence, you cannot use pinning with a #[repr(packed)] type.</p>
</blockquote>
<p>This all makes sense to me in this context. Am I understanding it right that obtaining a <code>Pin&lt;&amp;mut Option&lt;PackedType&gt;&gt;</code> is unsound? Because <code>Option</code> implements <a href="https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.as_pin_mut"><code>as_pin_mut</code></a>, which would ultimately allow you to <code>Pin</code> a repr(packed)` type? What about <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=1a62b7e3002bf44b6fd3955229dbb945">this code</a> then?</p>



<a name="227638896"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227638896" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227638896">(Feb 24 2021 at 17:31)</a>:</h4>
<p>I'm sure I'm missing something trivial here again…</p>



<a name="227640108"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227640108" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227640108">(Feb 24 2021 at 17:38)</a>:</h4>
<p>Is this saying that you must not obtain pinned references to <em>fields</em> of a packed ADT?</p>



<a name="227640820"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227640820" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227640820">(Feb 24 2021 at 17:42)</a>:</h4>
<p>But that would be superfluous, as you cannot (in the future, its a forward compat lint right now) obtain any kind of references to a packed structs anyway…</p>



<a name="227641430"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227641430" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227641430">(Feb 24 2021 at 17:45)</a>:</h4>
<p><span class="user-mention silent" data-user-id="123586">nagisa</span> <a href="#narrow/stream/122651-general/topic/nagisa.20doesn't.20understand.20pin.20again/near/227640108">said</a>:</p>
<blockquote>
<p>Is this saying that you must not obtain pinned references to <em>fields</em> of a packed ADT?</p>
</blockquote>
<p>I don't think so... But to be honest I don't know the answer...</p>



<a name="227641509"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227641509" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227641509">(Feb 24 2021 at 17:46)</a>:</h4>
<p>However the documentation says "this can never cause a problem in safe code because implementing a type that relies on pinning requires unsafe code",</p>



<a name="227641686"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227641686" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227641686">(Feb 24 2021 at 17:47)</a>:</h4>
<p>so I <em>guess</em> such "unsafe code" is <em>responsible</em> for problems.</p>



<a name="227641988"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227641988" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227641988">(Feb 24 2021 at 17:49)</a>:</h4>
<p>That is, unsafe code that assumes <code>PackedType</code> from <code>Pin&lt;&amp;mut PackedType&gt;</code> is pinned should never exist.<br>
But that's only my guess, I could be wrong...</p>



<a name="227687432"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227687432" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Gus Wynn <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227687432">(Feb 24 2021 at 22:41)</a>:</h4>
<p>I think in general the thing about Pin (and Unpin for that matter) that often confuses me is that some things aren't marked <code>unsafe</code> (like implementing Unpin). I think the reason some things that seem unsafe aren't is because they only become actual violations when a person writes incorrect unsafe code. The pin module docs get into this a bit, as <span class="user-mention" data-user-id="374396">@hyd-dev</span> mentioned</p>
<p>That said, <code>pin-project</code> straight up rejects structs that that are repr(packed), so perhaps something funky is going on here</p>



<a name="227691351"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227691351" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227691351">(Feb 24 2021 at 23:13)</a>:</h4>
<p>Yeah, the <code>Unpin</code> thing was exactly what I got super confused about the first time around: <a href="#narrow/stream/122651-general/topic/Manual.20implementations.20of.20Unpin.20can.20be.20unsound.3F/near/200737518">https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Manual.20implementations.20of.20Unpin.20can.20be.20unsound.3F/near/200737518</a></p>



<a name="227691422"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227691422" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227691422">(Feb 24 2021 at 23:14)</a>:</h4>
<p>but admittedly that time half of the problem was me not reading the std::pin docs through 3 times over before starting a thread.</p>



<a name="227691657"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227691657" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227691657">(Feb 24 2021 at 23:16)</a>:</h4>
<p>this time around I made sure to read the whole thing twice and then the relevant paragraph many times over. I even took a walk to give my brain time to process everything.</p>



<a name="227692231"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227692231" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227692231">(Feb 24 2021 at 23:21)</a>:</h4>
<p>I wonder if it would help if I managed (or failed) to actually construct an example that demonstrated the unsoundness here. I pondered the idea but due to how it only implicit involves moves that I've little control over, it also seems quite difficult to achieve.</p>



<a name="227696169"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/nagisa%20doesn%27t%20understand%20pin%20again/near/227696169" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/nagisa.20doesn&#x27;t.20understand.20pin.20again.html#227696169">(Feb 24 2021 at 23:55)</a>:</h4>
<p>I think that an example would be the following:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[repr(packed)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">a</span>: <span class="kt">u8</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">b</span>: <span class="kt">u16</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="c1">// #[pin_project]</span>
<span class="w">    </span><span class="n">c</span>: <span class="nc">OneAlignedPinSensitive</span><span class="p">,</span><span class="w"> </span><span class="c1">// !Unpin</span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">pin_project_foo_c</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span>: <span class="nc">Pin</span><span class="o">&lt;&amp;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Pin</span><span class="o">&lt;&amp;</span><span class="n">OneAlignedPinSensitive</span><span class="o">&gt;</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">foo</span><span class="p">.</span><span class="n">map_unchecked</span><span class="p">(</span><span class="o">|</span><span class="n">foo</span><span class="o">|</span><span class="w"> </span><span class="o">&amp;*</span><span class="n">ptr</span>::<span class="n">addr_of</span><span class="o">!</span><span class="p">(</span><span class="n">foo</span><span class="p">.</span><span class="n">c</span><span class="p">))</span><span class="w"> </span><span class="c1">// c is well-aligned</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="n">stuff</span><span class="p">(</span><span class="n">pin_project_foo_c</span><span class="p">(</span><span class="nb">Box</span>::<span class="n">pin</span><span class="p">(</span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="err">…</span><span class="w"> </span><span class="p">}).</span><span class="n">as_ref</span><span class="p">()));</span><span class="w"></span>
</code></pre></div>
<p>The idea is that when <code>Foo</code> is dropped, after having been pinned and having pin-projected to <code>c</code> at least once, we have to drop <code>c</code> <em>in place</em> before it is moved or deallocated. <code>c</code> is dropped by <code>Foo</code>'s implicit / "automatic" drop of its fields, and, because it is a <code>#[repr(packed)]</code> struct, there is no guarantee that such compiler-generated code does not move <code>c</code> before dropping it. For instance, it could do something along the lines of:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">FooUnpacked</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="cm">/* same definition as Foo */</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">_unpacked</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">FooUnpacked</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">a</span>: <span class="nc">ptr</span>::<span class="n">addr_of</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">a</span><span class="p">).</span><span class="n">read_unaligned</span><span class="p">(),</span><span class="w"></span>
<span class="w">    </span><span class="n">b</span>: <span class="nc">ptr</span>::<span class="n">addr_of</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">b</span><span class="p">).</span><span class="n">read_unaligned</span><span class="p">(),</span><span class="w"></span>
<span class="w">    </span><span class="n">c</span>: <span class="nc">ptr</span>::<span class="n">addr_of</span><span class="o">!</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">c</span><span class="p">).</span><span class="n">read_unaligned</span><span class="p">(),</span><span class="w"> </span><span class="c1">// c is *moved* before having been dropped</span>
<span class="p">};</span><span class="w"></span>
<span class="c1">// _unpacked is dropped, dropping the moved c.</span>
</code></pre></div>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>